home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
archiver
/
lzhsourc.lzh
/
LZH.SRC
/
LHARC.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-07-02
|
100KB
|
2,791 lines
/*{{{ defines*/
/*************************************************
LHarc version 1.13b (c)Yoshi, 1988-89.
main module : 1989/ 5/14
adaption to ATARI ST with TURBO-C 1.1
and some corrections
by J. Moeller 1990/01/31
Assembly and more corrections with
Turbo-C 1.0, 2.0, by Thomas Quester
HTAB = 4
*************************************************/
#define ThisSystem 'A' /* Atari */
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <process.h>
#include <stdlib.h>
#include <setjmp.h>
#include <errno.h>
#include <tos.h>
#ifdef Japanese
#include "usage_j.h"
#else
#ifdef German
#include "usage_d.h"
#else
#include "usage_e.h"
#endif
#endif
#define from extern
#ifndef __TOS__
#include <alloc.h>
#include <fcntl.h>
#include <io.h>
#include <dir.h>
#include <dos.h>
#else
#include <ext.h>
#include <tos.h>
#define MAXPATH 119
#define MAXDIR 102
#define MAXNUMFILES 128
#define far
#define huge
#define setmode(stream,mode) /* sorry: no such function known */
#include "goodputc.h"
#endif
#define UNKNOWNERR 0
#define INVCMDERR 1
#define MANYPATERR 2
#define NOARCNMERR 3
#define NOFNERR 4
#define NOARCERR 5
#define RENAMEERR 6
#define MKTMPERR 7
#define DUPFNERR 8
#define TOOMANYERR 9
#define TOOLONGERR 10
#define NOFILEERR 11
#define MKFILEERR 12
#define RDERR 13
#define WTERR 14
#define MEMOVRERR 15
#define INVSWERR 16
#define CTRLBRK 17
#define NOMATCHERR 18
#define COPYERR 19
#define NOTLZH 20
#define OVERWT 21
#define MKDIR 22
#define MKDIRERR 23
#define CRCERR 24
#define RDONLY 25
#ifndef __TOS__
#define PAGER "less"
#define BUFFERSIZ 4096L
#else
#define PAGER "less.ttp"
#define BUFFERSIZ 16384L
#endif
#define MAXBLK 64
#define MAX_PAT 512
#define FAULT 0
#define SUCCS ~FAULT
#ifndef __TOS__
#define getch() (bdos(0x08, 0, 0) & 0xff)
#endif
#define min(a,b) ((a>b) ? b : a)
typedef unsigned char uchar;
typedef unsigned int uint;
typedef unsigned long ulong;
FILE *file1, *file2, *file3;
from FILE *infile;
from FILE *outfile;
from int FileFits; /* 1, wenn File passt */
int cmd; /* command */
int cmdupdate; /* Not zero, when updating archive */
int errorlevel = 0; /* return value */
jmp_buf exit_jmp; /* Jump to exit of program */
extern long textsize; /* file size before compression */
extern long codesize; /* file size after compression */
from long blocksize; /* Bytes bis "*" (norm. 4096) */
long arcpos0; /* position pointer for archive */
uchar *basedir; /* base directory (home-directory) */
uchar *wdir = ""; /* work directory */
uchar workdir[MAXPATH]; /* work directory */
uchar *infname; /* input file name (for error message) */
uchar *outfname; /* output file name (for error message)*/
int attr; /* file attributes for search files */
int Nfile; /* number of files which was found */
/* >> fbmax is used to compute the total amout used by filenames << */
ulong fblft, fbsize;
ulong fbmax,fbfiles; /* for buffers handling file names */
#ifndef __TOS__
uint seg; /* beginning segment of file name buffers */
#endif
uchar far *fbuf, huge *fbnxt; /* pointer to file name buffers */
uchar arcname[MAXPATH]; /* archive name */
uchar pathname[MAXPATH]; /* work for file name (extracting) */
uchar dospathname[MAXPATH]; /* work for filename (8+3 chars) */
uchar filename[MAXPATH]; /* work for file name (for file in archive) */
uchar comment[MAXPATH]; /* Komments in archives */
uchar SystemId; /* Archiv createt on system */
uchar freezing=0; /* Enables extended headers */
uchar UseExthdr=0; /* 1, if gethdr has to use exthdrs */
int patno; /* No. of path names in command line */
int UnixFile; /* !=0 if filename is not 8+3 */
uchar patfile[MAX_PAT][12]; /* file name in command line */
uchar *patpath[MAX_PAT]; /* directory name in command line */
int patcnt[MAX_PAT]; /* counts which this name matched */
uchar patnul[] = "*.*"; /* default path name */
uchar backup1[MAXPATH], backup2[MAXPATH]; /* temporary file names */
char *TheInputBuf; /* Input-Buffer */
char *TheOutputBuf;
from int unpackable;
/* temporary file names */
uchar flg_r = 0, flg_p = 0, flg_x = 0, flg_m = 0;
uchar flg_a = 0, flg_c = 0, flg_v = 0, flg_w = 0;
uchar flg_d = 0, flg_u = 0, flg_s = 0, flg_k = 0;
uchar flg_e = 0;
uchar flg_unpacked; /* Set to 1, if 100% used in pack_afx */
uchar elen=3;
from uchar flg_n = 0;
uchar flg_t = 0;
uchar flg_5 = 0;
uchar flg_arc = 0,flg_backup=0;
uchar method=5, FlgMethod=5;
#ifdef __TOS__
uchar flg_h = 0;
#endif
/* switches */
uchar copying = 0; /* turn on when copying temporary file */
uchar crcflg = 0; /* force copyfile() to calculate CRC*/
uchar tstflg = 0; /* turn on in 't' command */
uchar swchar; /* switch character */
uchar *pager = PAGER; /* utility used in 'p /v' mode */
from uint crc; /* calculated CRC code */
uchar *keyword = ""; /* key word for auto-execution */
struct filebuf { /* work for file name buffer */
void far *next;
uchar fpos; /* position of file name */
uchar cpos; /* position of effective path name */
uchar dir[MAXDIR]; /* full path name */
} fb0, fb1;
extern char *errmes[]; /* array of pointers to error messages */
/* extern uchar use[]; */ /* usage */
extern uchar buf2[], buf3[]; /* I/O buffers */
#ifdef Japanese
/* routines for handling Japanese strings (import from util.c) */
extern uchar *j_strupr(uchar *p);
extern int j_strcmp(char *p, char *q);
extern uchar *j_strchr(char *p, uint c);
extern uchar *j_strrchr(char *p, uint c);
extern void slash2yen(uchar *p); /* convert '/' to '\' */
extern void yen2shlas(uchar *p);
#define strupr j_strupr
#define strcmp j_strcmp
#define strchr j_strchr
#define strrchr j_strrchr
#else
extern void slash2yen(uchar *p); /* convert '/' to '\' */
extern void yen2slash(uchar *p);
/* #define slash2yen(p) */ /*
extern void slash2yen(uchar *p); /* convert '/' to '\' */
#endif
extern int getfattr(uchar *fn); /* get file attributes */
extern void setfattr(uchar *fn, int attr);/* set file attributes */
#ifndef __TOS__
extern uchar getswchar(void); /* get switch character */
extern int test_afx(char *s); /* Überprüft, ob Datei gepackt ist */
#else
extern char *stpcpy (char *dest, char *source);
extern int mkdir (char *path);
#define getswchar() ('/')
#endif
#ifdef __TOS__
struct outbuf
{
char *ptr; /* aktuelles Zeichen */
char *last; /* letztes Zeichen */
char *base; /* erstes Zeichen */
FILE *file; /* dateiname */
} OutBufMem;
struct outbuf *OutBuf;
#endif __TOS__
extern void mkcrc (void); /* import from 'LZS.*' */
extern void copyfile (FILE *Source, FILE *Dest, long size);
extern void Encode (void); /* import from 'LZHUF.*' */
extern ulong encode5(ulong orgsize);
extern void init_encode5(void);
extern void EncodeOld(void);
extern void Decode (void);
extern void decode_lh5(ulong orgsize,ulong pacsize);
extern void DecodeOld(void);
extern char M_NOMATCHERR[];
extern char M_COPYERR[];
extern char M_NOTLZH[];
extern char M_OVERWT[];
extern char M_MKDIR[];
extern char M_MKDIRERR[];
extern char M_CRCERR[];
extern char M_RDONLY[];
struct ftime arcstamp /* = {0L} */; /* time stamp for archive */
struct LzHead { /* file header */
uchar HeadSiz, HeadChk, HeadID[5];
ulong PacSiz, OrgSiz; /* 16- and 32-bit Intel format !!!*/
struct ftime Ftime;
uint Attr;
uchar Fname[MAXPATH]; /* packed filename + crc */
} Hdr1, Hdr2;
#ifndef __TOS__
struct exeHead { /* EXE header for SFX */
uint exeID, byte, page, reloc;
uint hdrsize, minalloc, maxalloc, initSS;
uint initSP, chksum, initIP, initCS;
uint reloctab, overlay, dummy1, dummy2;
} ExeHdr = {
'MZ', 0, 0, 0, 2, 0, 0xffff, 0xfff0,
0x100, 0, 0x100, 0xfff0, 0x1e, 0, 0, 0
};
#endif
#define FTimeToUIntTime(t) ((((t.ft_hour << 6) | t.ft_min) << 5) | t.ft_tsec)
#define FTimeToUIntDate(t) ((((t.ft_year << 4) | t.ft_month) << 5) | t.ft_day)
#define FTimeToULong(t) (((ulong)FTimeToUIntDate(t) << 16) | \
(ulong)FTimeToUIntTime(t))
uchar mksum(struct LzHead *h);
#ifdef __TOS__
extern int argvmain (int, uchar **, uchar **);
static DTA _mydta;
#endif __TOS__
/*}}} */
/*{{{ setcrc:*/
#ifndef __TOS__
#define setcrc(h, crc) (*(uint *)(&(h)->Fname[1]+(h)->Fname[0])=(crc))
#define getcrc(h) (*(uint *)(&(h)->Fname[1]+(h)->Fname[0]))
#else
static void setcrc (struct LzHead *h, uint crc)
{
uchar *CrcPtr = &h->Fname[1] + h->Fname[0];
*CrcPtr++ = (uchar)(crc & 0xff);
*CrcPtr++ = (uchar)(crc >> 8);
*CrcPtr++ = (uchar)(ThisSystem); /* SystemId */
if (freezing==0) {
/* *CrcPtr++ = (uchar) 0;
*CrcPtr++ = (uchar) 0; */
}
}
/*}}} */
/*{{{ getcrc:*/
static uint getcrc (struct LzHead *h)
{
uchar *CrcPtr = &h->Fname[1] + h->Fname[0];
return ((uint)*CrcPtr) | ((uint)*(CrcPtr + 1) << 8);
}
#endif
/*}}} */
/*{{{ usage: display helps*/
/*******************************
display helps
*******************************/
void usage(void)
{
int i;
char *s,c;
s=use;
i=1;
while ( (c=*s++) != 0) {
if (c=='\n')
if (i++ == 24) {
fflush (stdin); /* wait for keystroke when used */
printf ("\n%s",M_PRESSKEY); /* with GEM-Desktop */
getch ();
putchar ('\n');
i=1;
}
putchar(c);
}
putchar ('\n');
longjmp (exit_jmp, 1);
}
/*}}} */
/*{{{ message: Display a message*/
/*******************************
display a message
*******************************/
void message(uchar *p, uchar *q)
{
if (flg_d == 0) {
printf("%s", p);
if (q) {
printf(" : '%s'", q);
}
printf("\n");
}
}
/*}}} */
/*{{{ error: process for an error*/
/*******************************
process for an error
*******************************/
void error(int errcode, uchar *p)
{
if (copying) { /* error during copying temporary? */
fprintf(stderr, "\n%s\n", M_COPYERR);
fclose(file1);
unlink(arcname); /* erase incomplete archive */
file1 = NULL;
}
fprintf(stderr, "\n%s", errmes[errcode]);
if (p) {
fprintf(stderr, " : '%s'", p);
}
fprintf(stderr, "\n");
if (file3) {
fclose(file3);
if (!cmdupdate) /* during extracting */
unlink(pathname); /* delete the file */
file3=NULL;
}
if (file1) {
fclose(file1);
if (cmdupdate) /* during updating */
rename(backup1, arcname); /* recover old archive */
}
if (file2) {
fclose(file2);
if (!copying) { /* if not copying */
unlink(backup2); /* delete temporary */
file2=NULL;
}
}
if (copying)
errorlevel = 3;
else
errorlevel = 2;
longjmp (exit_jmp, 1);
}
/*}}} */
/*{{{ userbreak: handle user break*/
/*******************************
handle user break
*******************************/
#ifndef __TOS__
void userbreak(void)
{
error(CTRLBRK, NULL);
}
#endif
/*}}} */
/*{{{ e_fopen: fopen with detecting error*/
/*******************************
fopen with detecting error
*******************************/
FILE *e_fopen(uchar *fname, uchar *mode, int errID)
{
FILE *f;
if ((f = fopen(fname, mode)) == NULL) {
if (errno == EACCES)
error(RDONLY, fname);
error(errID, fname);
}
return f;
}
/*}}} */
/*{{{ e_rename: rename with detecting erorr*/
/*******************************
rename with detecting error
*******************************/
void e_rename(uchar *old, uchar *new)
{
if (rename(old, new))
error(RENAMEERR, old);
}
/*}}} */
/*{{{ getyn: ask 'Y' or 'N'*/
/*******************************
ask 'Y' or 'N'
*******************************/
uint getyn(void)
{
uint yn;
do {
yn = toupper(getch());
#ifdef German
} while (yn != 'J' && yn != 'N');
#else
} while (yn != 'Y' && yn != 'N');
#endif
fprintf(stderr, "%c\n", yn);
#ifdef German
if (yn == 'J') yn = 'Y';
#endif
return yn;
}
/*}}} */
/*{{{ getynr: ask 'Y', 'N' or 'R'*/
/*******************************
ask 'Y' or 'N'
*******************************/
uint getynr(void)
{
uint yn;
do {
yn = toupper(getch());
#ifdef German
} while (yn != 'J' && yn != 'N' && yn != 'R');
#else
} while (yn != 'Y' && yn != 'N' && yn != 'R');
#endif
fprintf(stderr, "%c\n", yn);
#ifdef German
if (yn == 'J') yn = 'Y';
#endif
return yn;
}
/*}}} */
/*{{{ extfn: File name -> internal format*/
/*******************************
file name -> internal format
*******************************/
void extfn(uchar *p, uchar *pb)
{
int i;
uchar * q;
if ((q = strrchr(p, '\\')) != NULL ||
(q = strchr(p, ':')) != NULL)
p = q + 1;
q = p;
for (i = 8; i > 0; i--, pb++) {
switch (*p) {
case '*':
*pb = '?';
break;
case '.':
case '\0':
*pb = ' ';
break;
default:
*pb = *p++;
}
}
while (+(*p != '\0' && *p++ != '.'));
for (i = 3; i > 0; i--, pb++) {
switch (*p) {
case '*':
*pb = '?';
break;
case '\0':
*pb = ' ';
break;
default:
*pb = *p++;
}
}
*q = *pb = '\0';
}
/*}}} */
/*{{{ packfn: internal format -> file name*/
/*******************************
internal format -> file name
*******************************/
void packfn(uchar *p, uchar *q)
{
int i;
for (i = 8; i > 0; i--) {
if (*q != ' ')
*p++ = *q;
q++;
}
*p++ = '.';
for (i = 3; i > 0; i--) {
if (*q != ' ')
*p++ = *q;
q++;
}
if (p[-1] == '.')
p--;
*p = '\0';
}
/*}}} */
/*{{{ backpath get back to parent directory*/
/*******************************
get back to parent directory
*******************************/
uchar *backpath(uchar *p)
{
uchar *q;
if ((q = strrchr(p, '\\')) == NULL &&
(q = strchr(p, ':')) == NULL) {
*p = '\0';
q = p;
} else {
*++q = '\0';
}
return q;
}
/*}}} */
/*{{{ tstpat : whether path name was used or not*/
/***********************************
whether path name was used or not
***********************************/
void tstpat(void)
{
int i, cnt;
uchar path[MAXPATH];
cnt = 0;
for (i = 0; i < patno; i++)
cnt += patcnt[i];
if (cnt == 0) /* no file matched */
error(NOFILEERR, NULL);
for (i = 0; i < patno; i++) {
if (patcnt[i] == 0) { /* if any path name was not used */
packfn(stpcpy(path, patpath[i]), patfile[i]);
fprintf(stderr, "%s : '%s'\n", M_NOMATCHERR, path);
errorlevel = 1; /* display warning */
}
}
}
/*}}} */
/*{{{ sethdr: make a file header*/
/*******************************
make a file header
*******************************/
void sethdr(uchar *fn, uint attr, struct LzHead *h)
{
uint l;
memset(h, 0, sizeof(struct LzHead));
l = (uint)strlen(fn); /* length of file name */
h -> Fname[0] = l;
memcpy(h -> Fname + 1, fn, l);
l += 20 + elen +2; /* size of header */
h -> HeadSiz = l;
fseek(file3, 0L, SEEK_END);
h -> OrgSiz = textsize = ftell(file3); /* original size of a file */
h -> PacSiz = codesize = 0;
method=FlgMethod;
/* if (h->OrgSiz < 5000 && FlgMethod==5) method=1; */
rewind(file3);
getftime(fileno(file3), &(h -> Ftime)); /* get time stamp */
h -> Attr = attr; /* file attributes */
if (method==0) memcpy(h->HeadID,"-lz5-",5);
if (method==1) memcpy(h->HeadID,"-lh1-",5);
if (method==5) memcpy(h->HeadID,"-lh5-",5);
if (cmd== 'C') memcpy(h->HeadID,"-afx-",5);
}
/*}}} */
/*{{{ wthdr680x0: write a file header on atari (or any system)*/
#ifdef __TOS__
/*******************************
write a file header on
Atari ST (680x0)
*******************************/
int wthdr680x0 (register struct LzHead *h,
FILE *file)
{
uchar buffer [256];
uchar chksum,*ptr2;
int comlen;
register uchar *ptr,*co,*ptr1;
union { uint x;
uchar bytes [2]; } swap16;
union { ulong x;
uchar bytes [4]; } swap32;
register int i;
int len;
char c;
if (comment[0] == 0) comlen = 0; else
{ comlen = 4 + strlen(comment);
h->PacSiz += comlen; }
if (flg_s) yen2slash(&(h->Fname));
h -> HeadChk = mksum(h); /* header sum */
ptr = buffer;
*ptr++ = h->HeadSiz;
*ptr++ = h->HeadChk;
for (i = 0; i < 5; i++)
*ptr++ = h->HeadID [i];
swap32.x = h->PacSiz;
for (i = 3; i >= 0; i--) /* convert motorola --> intel */
*ptr++ = swap32.bytes [i];
swap32.x = h->OrgSiz;
for (i = 3; i >= 0; i--) /* convert motorola --> intel */
*ptr++ = swap32.bytes [i];
swap32.x = FTimeToULong (h->Ftime);
for (i = 3; i >= 0; i--) /* convert motorola --> intel */
*ptr++ = swap32.bytes [i];
swap16.x = h->Attr;
for (i = 1; i >= 0; i--) /* convert motorola --> intel */
*ptr++ = swap16.bytes [i];
len = *ptr++ = h->Fname [0];
for (i = 1; i <= len + elen+2; i++) *ptr++ = h->Fname[i];
if (freezing && flg_k==0) {
ptr2=ptr-1;
if (comlen) {
ptr-=2;
*ptr++=comlen;
*ptr++=0;
*ptr++=0x3f;
co=comment;
while (*co) *ptr++=*co++;
*ptr++=0xff;
*ptr++=0x0;
*ptr++=0x0;
}
ptr1=&buffer[2];
chksum=0;
while (ptr1 != ptr2)
chksum = chksum + *ptr1++;
buffer[1]=chksum;
len = (int) fwrite (buffer, ptr-buffer , 1, file);
} else
len = (int) fwrite (buffer, h->HeadSiz +2 , 1, file);
/* slash2yen(&(h->Fname)); */
h -> HeadChk = mksum(h); /* header sum */
return len;
}
#endif
/*}}} */
/*{{{ wthdr: write a file header*/
/*******************************
write a file header
*******************************/
void wthdr(struct LzHead *h)
{
arcpos0 = ftell(file2); /* memorize this position */
#ifndef __TOS__
if (fwrite(h, h -> HeadSiz + 2, 1, file2) == 0)
error(WTERR, backup2);
#else
if (wthdr680x0 (h, file2) == 0)
error(WTERR, backup2);
#endif
}
/*}}} */
/*{{{ mksum: calculate check-sum*/
/*******************************
calculate check-sum of header
*******************************/
uchar umksum(struct LzHead *h)
{
uchar *p, *q;
uchar i;
p = (uchar *)h ;
q = p + h -> HeadSiz;
p+=2; q+=2;
for (i = 0; p < q; p++)
i += *p;
return i;
}
#ifndef __TOS__
uchar mksum(struct LzHead *h)
{
uchar *p, *q;
uchar i;
p = (uchar *)h + 2;
q = p + h -> HeadSiz;
for (i = 0; p < q; p++)
i += *p;
return i;
}
#else
uchar mksum(struct LzHead *h)
{
union { uint x;
uchar bytes [2]; } swap16;
union { ulong x;
uchar bytes [4]; } swap32;
char *s;
register uchar sum;
register int i;
int len;
sum = 0;
for (i = 0; i < 5; i++)
sum += h->HeadID [i];
swap32.x = h->PacSiz;
for (i = 3; i >= 0; i--)
sum += swap32.bytes [i];
swap32.x = h->OrgSiz;
for (i = 3; i >= 0; i--)
sum += swap32.bytes [i];
swap32.x = FTimeToULong (h->Ftime);
for (i = 3; i >= 0; i--)
sum += swap32.bytes [i];
swap16.x = h->Attr;
for (i = 1; i >= 0; i--)
sum += swap16.bytes [i];
sum += h->Fname [0];
len = (int) h->Fname [0];
s=h->Fname; s++;
for (i = 1; i <= h->HeadSiz - 20; i++)
sum += *s++;
return sum;
}
#endif
/*}}} */
/*{{{ remkhdr: remake file header and write*/
/*******************************
remake file header & write
*******************************/
void remkhdr(struct LzHead *h)
{
int flg;
long arcpos1;
flg = 0;
h -> PacSiz = codesize; /* packed size of a file */
setcrc (h, crc);
flg_unpacked=0;
if (h -> OrgSiz <= codesize && flg_5==0) { /* if packed size >= original size */
flg = 1; /* select method "simple copy" */
flg_unpacked=1;
memcpy(h->HeadID,"-lh0-",5);
h -> PacSiz = h -> OrgSiz;
}
h -> HeadChk = mksum(h); /* header sum */
if (flg_u && flg_5 == 0) { /* without compression */
crcflg=1; crc=0;
copyfile(file3, file2, h -> OrgSiz); /* do simple copy */
flg = 0;
setcrc(h,crc);
}
arcpos1 = ftell(file2); /* memorize this position */
fseek(file2, arcpos0, SEEK_SET); /* seek to header */
#ifndef __TOS__
fwrite(h, h -> HeadSiz + 2, 1, file2); /* rewrite header */
#else
wthdr680x0 (h, file2);
#endif
if (flg && flg_5 == 0) {
rewind(file3);
copyfile(file3, file2, h -> OrgSiz); /* do simple copy */
} else {
fseek(file2, arcpos1, SEEK_SET); /* return to the end */
}
}
/*}}} */
/*{{{ rdhdr680x0: read a file header on Atari*/
#ifdef __TOS__
/*******************************
read a file header on
Atari ST (680x0)
*******************************/
int rdhdr680x0 (register struct LzHead *h,
FILE *file)
{
uchar buffer [sizeof (struct LzHead)];
register uchar *ptr;
union { uint x;
uchar bytes [2]; } swap16;
union { ulong x;
uchar bytes [4]; } swap32;
register int i;
int len;
if ((h -> HeadSiz = getc (file)) <= 0 ||
ferror (file) ||
h->HeadSiz > sizeof buffer - 1 ||
fread (buffer, (int) h->HeadSiz + 1, 1, file) == 0)
{
return FAULT;
}
ptr = buffer;
h->HeadChk = *ptr++;
for (i = 0; i < 5; i++)
h->HeadID [i] = *ptr++;
for (i = 3; i >= 0; i--) /* convert intel --> motorola */
swap32.bytes [i] = *ptr++;
h->PacSiz = swap32.x;
for (i = 3; i >= 0; i--) /* convert intel --> motorola */
swap32.bytes [i] = *ptr++;
h->OrgSiz = swap32.x;
for (i = 3; i >= 0; i--) /* convert intel --> motorola */
swap32.bytes [i] = *ptr++;
h->Ftime.ft_tsec = (uint)(swap32.x & 0x1f);
h->Ftime.ft_min = (uint)((swap32.x >> 5) & 0x3f);
h->Ftime.ft_hour = (uint)((swap32.x >> 11) & 0x1f);
h->Ftime.ft_day = (uint)((swap32.x >> 16) & 0x1f);
h->Ftime.ft_month = (uint)((swap32.x >> 21) & 0x0f);
h->Ftime.ft_year = (uint)((swap32.x >> 25) & 0x7f);
for (i = 1; i >= 0; i--) /* convert intel --> motorola */
swap16.bytes [i] = *ptr++;
h->Attr = swap16.x;
for (i=0;i<=MAXPATH;i++) h->Fname[i]=0;
len = h->Fname [0] = *ptr++;
for (i = 1; i <= h->HeadSiz - 20; i++)
h->Fname [i] = *ptr++;
return SUCCS;
}
#endif
/*}}} */
/*{{{ gethdr : get a file header*/
/*******************************
get a file header
*******************************/
uchar *gethdr(FILE *arc, struct LzHead *h)
{
uchar *q,*p,*p1, i;
uint extsize;
char exthdr[256];
char fname[256];
#ifndef __TOS__
if ((h -> HeadSiz = getc(arc)) <= 0 ||
h -> HeadSiz > sizeof(struct LzHead) - 3 ||
fread(&(h -> HeadChk), h -> HeadSiz + 1, 1, arc) == 0)
{ /* read file header */
return NULL;
}
#else
if (!rdhdr680x0 (h, arc))
return NULL;
#endif
if (mksum(h) != h -> HeadChk)
if (umksum(h) != h -> HeadChk) /* if sum is wrong */
return NULL;
i = *(h -> Fname);
strncpy(filename, h -> Fname + 1, i);
*(filename + i) = '\0';
if ( (flg_k == 0) && UseExthdr) {
extsize=h->Fname[h->Fname[0]+4];
SystemId = h->Fname[h->Fname[0]+3];
comment[0] = 0; /* Prevent showing an illegal comment */
if (extsize != 0) {
fread(exthdr,1,extsize-2,arc);
/* h->PacSiz-=extsize;
extsize=fgetc(arc);
extsize+=(uint)fgetc(arc)<<8; */
while (extsize != 0) {
if (exthdr[0] == 2) { /* pathname-header */
p=fname; p1=&exthdr[1];
while ( (*p++=*p1++) != 0xff);
p--;
*p++='\\';
strcpy(p,filename);
strcpy(filename,fname);
}
if (exthdr[0] == 0x3f) { /* Komment - Header */
p=comment;p1=&exthdr[1];
while ((*p++=*p1++) != 0xff); p--; *p=0;
}
h->PacSiz-=extsize;
extsize=fgetc(arc);
extsize+=(uint)fgetc(arc)<<8;
if (extsize) {
if (extsize > 250) {
fseek(arc,extsize-2,SEEK_CUR); /* Header to long, skip */
exthdr[0]=255; }
else {
fread(exthdr,1,extsize-2,arc);
}
}
}
}
}
if ((q = strrchr(filename, '\\')) == NULL &&
(q = strrchr(filename, '/')) == NULL &&
(q = strchr(filename, ':')) == NULL)
q = filename;
else
q++;
return q; /* return the portion of file name */
}
/*}}} */
/*{{{ matchpat: test match of file name*/
/*******************************
test match of file name
*******************************/
int matchpat(uchar *p)
{
uchar buf[12], name[MAXPATH];
int i, j, retcode;
retcode = FAULT;
strcpy(name, p);
extfn(name, buf);
for (i = 0; i < patno; i++) {
if (flg_p || *patpath[i]) { /* should compare full path ? */
if (strcmp(name, patpath[i]))
continue;
}
for (j = 0; j < 11; j++) { /* compare file name */
if (patfile[i][j] != buf[j] && patfile[i][j] != '?')
break;
}
if (j == 11) { /* if matched */
patcnt[i]++;
retcode = SUCCS;
}
}
return retcode;
}
/*}}} */
/*{{{ ratio: ratio * 1000*/
/*******************************
ratio * 1000
*******************************/
uint ratio(ulong a, ulong b)
{
int i;
if (!b) return 0; /* if diviser == 0 */
for (i = 0; i < 3 && a < 0x19999999L; i++) {
a *= 10; /* while not overflow */
} /* upto 1000 times */
for (; i < 3; i++) { /* the case of overflow */
b /= 10;
}
a += b / 2; /* for round up */
return (uint)(a / b); /* return (a * 1000 / b) */
}
/*}}} */
/*{{{ cmpname: compare names*/
/*******************************
compare names
*******************************/
int cmpname(uchar *f0, uchar *f1, uchar *p0, uchar *p1)
{
int c;
c = strcmp(f0, f1); /* compare only file names */
if (c == 0) {
c = (int)(strlen(p0) - strlen(p1)); /* compare lengths of path names */
if (c == 0) {
c = strcmp(p0, p1); /* compare path names */
}
}
return c;
}
/*}}} */
/*{{{ regfile: regist file names*/
/*******************************
regist file names
*******************************/
int regfile(uchar *p, uchar *q, uchar *f, int attrib)
/*
p: full path name including base directory
q: directory name to be registed
f: file name
*/
{
uchar path[MAXPATH];
struct filebuf far *f0;
struct filebuf far *f1;
uchar *s;
int c,size;
if (flg_arc)
if ((attrib & 0x20) == 0) return 0;
if (strstr(f, "LHARC.)1(") || strstr(f, "LHARC.)2("))
return 0; /* temporary file ? */
stpcpy(stpcpy(path, q), f);
stpcpy(s = stpcpy(fb1.dir, p), f);
fb1.fpos = s - (uchar *)&fb1;
fb1.cpos = flg_x ? (q - p) + (fb1.dir - (uchar *)&fb1) : fb1.fpos;
if (fbuf == NULL) { /* for first entry */
fbfiles=0; /* >> Number of files matched << */
#ifndef __TOS__
if (allocmem(fbsize = 0x100, &seg) != -1)
error(MEMOVRERR, NULL);
fbuf = (uchar far *)fbnxt = MK_FP(seg, 0);
fbleft = 0x100;
#else
/* >> get all the memory. fbmax holds the number of bytes available << */
fbsize=sizeof(struct filebuf) * MAXNUMFILES;
fbmax= (long) Malloc(-1);
fbuf = fbnxt = Malloc(fbmax);
if (fbuf == NULL)
error(MEMOVRERR, NULL);
fblft = fbmax;
#endif
*(long far *)fbuf = 0;
fbnxt += 4;
}
f0 = (struct filebuf far *)fbuf;
do { /* search position in which should be inserted*/
f1 = f0;
if ((f0 = f0 -> next) == NULL)
break;
fb0 = *f0;
c = cmpname((uchar *)&fb0 + fb0.fpos, (uchar *)&fb1 + fb1.fpos,
(uchar *)&fb0 + fb0.cpos, (uchar *)&fb1 + fb1.cpos);
} while (c < 0);
if (f0 && c == 0 && strcmp(fb0.dir, fb1.dir)) {
error(DUPFNERR, (uchar *)&fb1 + fb1.cpos);
} /* same registing names of different files */
if (f0 == NULL || c) { /* do regist */
size = (int)(strlen(fb1.dir) +
(fb1.dir - (uchar *)&fb1)) + 1;
#ifndef __TOS__
if (fblft < sizeof(struct filebuf)) { /* if buffer is short */
if (setblock(seg, fbsize += 0x100) != -1)
error(TOOMANYERR, NULL);
fblft += 0x100;
}
#else
size += size & 1; /* size must be even to avoid address error! */
if (fblft < sizeof (struct filebuf))
error(TOOMANYERR, NULL);
#endif
fb1.next = f0;
f0 = (struct filebuf far *)fbnxt;
f1 -> next = f0;
*f0 = fb1;
fblft -= size;
fbnxt += size;
fbfiles++; /* >> Count files << */
}
return 1;
}
/*}}} */
/*{{{ travel: recursive collection of files*/
/*******************************
recursive collection of files
*******************************/
int travel(uchar *p, uchar *q, uchar *f)
{
struct ffblk ffb;
static uchar buf[12];
uchar *r, *s;
int done, cnt, j;
cnt = 0;
if (flg_r == 1 || strrchr(q, '\\') == q + strlen(q) - 1) {
stpcpy(s = q + strlen(q), "*.*");
}
done = findfirst(p, &ffb, attr); /* search the first file */
s = backpath(q);
while (! done) {
if (ffb.ff_attrib & 0x10) { /* if this is a sub-directory */
if (ffb.ff_name[0] != '.') {
r = stpcpy(stpcpy(s, ffb.ff_name), "\\");
if (r - p > MAXPATH)
error(TOOLONGERR, p);
cnt += travel(p, q, f); /* search recursively */
*s = '\0';
}
} else /* if this is a file */
if (flg_r == 2) { /* in /r2 mode */
cnt += regfile(p, q, ffb.ff_name,ffb.ff_attrib); /* regist name */
} else { /* in /r+ mode */
stpcpy(s, ffb.ff_name);
extfn(s, buf);
for (j = 0; j < 11; j++) { /* test file names */
if (f[j] != buf[j] && f[j] != '?')
break;
}
if (j == 11) {
cnt += regfile(p, q, ffb.ff_name,ffb.ff_attrib); /* if match, regist */
}
}
done = findnext(&ffb);
}
return cnt; /* number of registed files */
}
/*}}} */
/*{{{ findfile: non-recursive collection of files*/
/**********************************
non-recursive collection of files
**********************************/
int findfile(uchar *p, uchar *q)
{
struct ffblk ffb;
int done, cnt;
cnt = 0;
done = findfirst(p, &ffb, attr);
backpath(p);
while (! done) {
cnt += regfile(p, q, ffb.ff_name,ffb.ff_attrib);
done = findnext(&ffb);
}
return cnt;
}
/*}}} */
/*{{{ mklilst: make file list to append*/
/*******************************
make file lists to append
*******************************/
void mklist(void)
{
uchar path[MAXPATH], *p, *q, *r;
int i, cnt;
Nfile = 0;
if (flg_a) { /* set attributes for search */
attr = 0x07;
} else {
attr = 0;
}
if (flg_r) {
attr |= 0x10;
}
for (i = 0; i < patno; i++) {
p = patpath[i];
q = path;
if (*p && p[1] == ':') { /* if path name includes drive */
q = stpcpy(path, p); /* ignore base directory */
r = path + 2; /* don't regist drive name */
} else {
q = stpcpy(r = stpcpy(path, basedir), p);
}
if (flg_r == 1) { /* /r+ mode */
cnt = travel(path, r, patfile[i]);
} else if (flg_r > 1) { /* /r2 mode */
packfn(q, patfile[i]);
cnt = travel(path, r, NULL);
} else { /* /r- mode */
packfn(q, patfile[i]);
cnt = findfile(path, r);
}
Nfile += patcnt[i] = cnt;
}
#ifdef __TOS__
/* >> After registering all files, free the unused memory << */
Mshrink(0,fbuf,fbmax-fblft+5);
if (flg_d == 0) printf("Files matched: %ld\n",fbfiles);
#endif
}
/*}}} */
/*{{{ mkhdr: make file header*/
/*******************************
make file header
*******************************/
uchar *mkhdr(struct filebuf far *f, struct LzHead *h)
{
int attr;
fb0 = *f;
attr = getfattr(fb0.dir);
file3 = e_fopen(fb0.dir, "rb", RDERR);
sethdr((uchar *)&fb0 + fb0.cpos, attr, h);
return (uchar *)&fb0 + fb0.fpos; /* position of file name */
}
extern uint blkcnt;
uint curcnt;
uint nxtcnt;
/*}}} */
/*{{{ blkdisp: calculate and display*/
/*******************************
calculate and display
for indicator
*******************************/
void blkdisp(long l, char *s) {
uint i;
if (flg_n == 0) {
blocksize=4096;
printf("\n %s : ", s);
blkcnt = (uint)((l + 4095) / 4096);
if (blkcnt > MAXBLK) {
blkcnt = MAXBLK;
blocksize= l / MAXBLK;
}
i = blkcnt;
while (i-- > 0) {
putchar('.');
}
printf("\r %s : ", s);
curcnt = nxtcnt = 0;
} else {
curcnt = 0;
nxtcnt = -1;
}
}
/*}}} */
/*{{{ curback: let cursor back after displaying indicator*/
/*******************************
let cursor back after
displaying indicator
*******************************/
void curback(void)
{
if (flg_n == 0) {
printf("\r ");
}
}
/*}}} */
/*{{{ MKinputbuf: make buffers for reading*/
/* Try to read the complete file. If the position is odd, begin reading at */
/* an even position and dicard one byte */
void MKinputbuf(long filesize)
{
long bufsize;
long Pos;
bufsize=(long)Malloc(-1)-50000;
if (bufsize < 0) bufsize=8192;
bufsize=min(filesize,bufsize)+1024;
TheInputBuf=(char *) Malloc(bufsize+2);
if (TheInputBuf < 0) error(MEMOVRERR,NULL);
if (TheInputBuf>0) {
if ((bufsize & 1) == 1) bufsize--; /* Make bufsize even */
if ((ftell(infile) & 1) == 1) { /* Odd position */
fseek(infile,ftell(infile)-1,0); /* go to even pos. */
setvbuf(infile,TheInputBuf, _IOFBF, bufsize); /* set buffer */
getc(infile); /* fill buffer, dicard char */
} else
{ fseek(infile,ftell(infile),0); /* even position is ok */
setvbuf(infile,TheInputBuf, _IOFBF, bufsize);
}
FileFits=1; /* signal file fits into mem */
} else FileFits=0;
}
/*}}} */
/*{{{ mkoutboutb Make buffers for writing*/
void MKoutputbuf( void )
{
long bufsize;
char *start,ende;
bufsize=(long)Malloc(-1)-20000;
TheOutputBuf=Malloc(bufsize);
fseek(outfile,ftell(outfile),0);
if (TheOutputBuf>0) {
setvbuf(outfile,TheOutputBuf,_IOFBF,bufsize);
} else {
setvbuf(outfile,buf3,_IOFBF,BUFFERSIZ);
}
}
/*}}} */
/*{{{ freeze: freeze a file*/
/*******************************
freeze a file
*******************************/
void freeze(uchar *p)
{
char *hp;
char iname[128];
if (FTimeToULong (arcstamp) < FTimeToULong (Hdr2.Ftime))
arcstamp = Hdr2.Ftime;
strcpy(iname,p);
freezing=1;
if (flg_d == 0) printf("%s ", p);
if (flg_e) { /* Enter comment THQ */
printf("\n");
printf(M_COMMENT);
gets(comment);
}
if (method!=5)
blkdisp(Hdr2.OrgSiz, "Freezing ");
else
blkdisp(Hdr2.OrgSiz/2, "Freezing ");
wthdr(&Hdr2);
if (method == 5) init_encode5();
setvbuf(file3, buf3, _IOFBF, BUFFERSIZ);
infile = file3;
outfile = file2;
MKinputbuf(Hdr2.OrgSiz);
infname = p;
textsize = Hdr2.OrgSiz;
crc = 0;
codesize=0;
if (flg_u) codesize = Hdr2.OrgSiz + 1; else {
if (method==0) EncodeOld();
if (method==1) Encode();
if (method==5) codesize=encode5(Hdr2.OrgSiz);
}
fflush(outfile);
fseek(infile,ftell(infile),0);
setvbuf(file3,buf3,_IOFBF,BUFFERSIZ);
fseek(file2,0,SEEK_END);
Mfree(TheInputBuf);
if (flg_backup)
Fattrib(iname,1,Fattrib(iname,0,0) & 0xff-0x20);
remkhdr(&Hdr2);
curback();
if (flg_d == 0) printf("Frozen(%3d%%) \n", ratio(Hdr2.PacSiz, Hdr2.OrgSiz) / 10);
comment[0] = 0;
freezing=0;
}
/*}}} */
/*{{{ copyold: copy file from old archiv*/
/*******************************
Copy a file from
old archive
*******************************/
void copyold(void)
{
if (FTimeToULong (arcstamp) < FTimeToULong (Hdr1.Ftime))
arcstamp = Hdr1.Ftime;
wthdr(&Hdr1); /* copy from old archive */
copyfile(file1, file2, Hdr1.PacSiz);
}
/*}}} */
/*{{{ execappend: execute one of a, u, m commands*/
/*******************************
execute one of a, u, m
commands
*******************************/
int execappend(void)
{
struct filebuf far *f0;
uchar *p, *q;
int c, d;
int cnt = 0;
q = file1 ? gethdr(file1, &Hdr1) : NULL; /* read header from old arc */
if ((f0 = ((struct filebuf far *)fbuf) -> next) != NULL) {
p = mkhdr(f0, &Hdr2); /* make header from the file list */
}
while (1) {
if (f0 == NULL) {
d = 1;
if (q == NULL)
break;
} else if (q == NULL) {
d = -1;
} else {
d = cmpname(p, q, (uchar *)&fb0 + fb0.cpos, filename);
}
c = d;
if (c == 0) {
if (flg_c || FTimeToULong (Hdr1.Ftime) <
FTimeToULong (Hdr2.Ftime)) {
c = -1;
} else {
c = 1;
}
}
if (c < 0) { /* freeze a new file */
if (d == 0) {
fseek(file1, Hdr1.PacSiz, SEEK_CUR);
q = gethdr(file1, &Hdr1); /* skip a file in old */
} /* archive */
freeze(fb0.dir);
fclose(file3);
cnt++;
if ((f0 = fb0.next) != NULL) { /* make header of the next */
p = mkhdr(f0, &Hdr2); /* file in file list */
}
} else { /* copy a file from old archive */
if (d == 0) {
fclose(file3);
if ((f0 = fb0.next) != NULL) { /* make header of the next */
p = mkhdr(f0, &Hdr2); /* file in file list */
}
}
copyold();
q = gethdr(file1, &Hdr1); /* get the next header */
} /* in old archive */
}
return cnt;
}
/*}}} */
/*{{{ delfile: delete files after execution of updating in 'm' command*/
/*******************************
delete files after
execution of updating
in 'm' command
*******************************/
void delfile(void)
{
struct filebuf far *f0;
struct filebuf fb0;
f0 = (struct filebuf far *)fbuf;
while ((f0 = f0 -> next) != NULL) {
fb0 = *f0;
unlink(fb0.dir);
};
}
/*}}} */
/*{{{ openarc1: open an old archiv*/
/*******************************
open an old archive
*******************************/
void openarc1(void)
{
uchar *p, *q;
file1 = e_fopen(infname = arcname, "rb", NOARCERR);
/* >> Because some SFX-Versions for the ST have a header bigger 2048 Bytes
4096 bytes are read here << */
q = buf2 - 5 + fread(buf2, 1, 4096, file1);
for (p = buf2; p < q; p++) {
if (p[0] == '-' && p[4] == '-')
if (p[1] == 'l' || p[1] == 'a') break;
}
if (p >= q) {
error(NOFILEERR, arcname);
}
fseek(file1, (long)(p - buf2 - 2), SEEK_SET);
}
/*}}} */
/*{{{ openrwarc1: open an archiv in rd/wt for testing read-only*/
/*******************************
open an archive in rd/wt
for testing read-only
*******************************/
void openrwarc1(void)
{
file1 = e_fopen(arcname, "r+b", NOARCERR);
}
/*}}} */
/*{{{ openbackup1 close an old archiv & rename to temporary*/
/*******************************
close an old archive
& rename to temporary
*******************************/
static void openbackup1(void)
{
fclose(file1);
stpcpy(backpath(strcpy(backup1, arcname)), "lharc.)1(");
e_rename(arcname, backup1);
file1 = fopen(infname = backup1, "rb");
}
/*}}} */
/*{{{ openbackup2 open a temporary file for a new archiv*/
/*******************************
open a temporary file
for a new archive
*******************************/
static void openbackup2(void)
{
if (flg_w) {
stpcpy(stpcpy(backup2, workdir), "lharc.)2(");
} else {
strcat(backpath(strcpy(backup2, arcname)), "lharc.)2(");
}
file2 = e_fopen(outfname = backup2, "w+b", MKTMPERR);
setvbuf(file2, buf2, _IOFBF, BUFFERSIZ);
}
/*}}} */
/*{{{ stclosearc: set time & close an archive*/
/*******************************
set time & close an archive
*******************************/
void stclosearc(FILE *f)
{
if (flg_t) {
fflush(f);
setftime(fileno(f), &arcstamp);
}
fclose(f);
}
/*}}} */
/*{{{ endofupdate end-of-job process in making new archive*/
/*******************************
end-of-job process
in making new archive
*******************************/
void endofupdate(int cnt)
{
if (file1)
stclosearc(file1);
tstpat();
if (cnt) { /* if any files are manipulated */
if (file1)
if (unlink(backup1)) /* delete an old archive */
printf("debug : Failed in deleting '%s'.", backup1);
if ((arcpos0 = ftell(file2)) != 0) {
if (putc(0, file2) == EOF)
error(WTERR, backup2);
if (flg_w) { /* if work directory is assigned */
rewind(file2);
infname = backup2;
copying = 1; /* copy temporary to new archive */
file1 = e_fopen(outfname = arcname, "wb", MKFILEERR);
if (flg_d == 0) printf("Copying Temp to Archive ...");
copyfile(file2, file1, arcpos0 + 1);
if (flg_d == 0) printf("\n");
copying = 0;
stclosearc(file1);
fclose(file2);
unlink(backup2);
} else {
stclosearc(file2); /* else rename temporary to archive */
rename(backup2, arcname);
}
} else {
fclose(file2);
unlink(backup2);
}
} else { /* if no change was made in archive */
fclose(file2);
unlink(backup2);
rename(backup1, arcname); /* restore the old archive */
}
}
/*}}} */
/*{{{ append: a,u,m command*/
/*******************************
a, u, m command
*******************************/
void append(void)
{
int cnt;
file1 = fopen(arcname, "r+b");
if (file1) {
openbackup1(); /* if archive presents, rename to temp */
} else {
if (errno == EACCES)
error(RDONLY, arcname); /* read-only error */
}
mklist(); /* make a file list */
if (Nfile == 0) {
error(NOFILEERR, NULL);
}
if (file1) {
message("Updating archive", arcname);
} else {
message("Creating archive", arcname);
}
openbackup2(); /* open temporary for new archive */
cnt = execappend(); /* execute updating archive */
endofupdate(cnt); /* end-of-job process */
if (cmd == 'M')
delfile(); /* if 'm' command, delete files */
#ifndef __TOS__
freemem(seg);
#else
free (fbuf);
#endif
}
/*}}} */
/*{{{ open_afxb: open backup-file for afx*/
void open_afxbackup(char *s)
{
char *p,*d,c;
p=backup2; d=p; *backup2='\0';
while ( (c=*s++) != 0) {
if ((c=='\\') || (c==':'))
d=p+1;
*p++=c;
}
strcpy(d,"__temp__.lzs");
file2=e_fopen(outfname=backup2,"w+b",MKTMPERR);
setvbuf(file2,buf2,_IOFBF,BUFFERSIZ);
}
/*}}} */
/*{{{ pack_aafx: subprocess in packing afx*/
void pack_aafx(void)
{
struct filebuf far *f0;
uchar *p, *q;
int c, d;
int cnt = 0;
if ((f0 = ((struct filebuf far *)fbuf) -> next) != NULL) {
p = mkhdr(f0, &Hdr2); /* make header from the file list */
}
while (f0 != NULL) {
switch(test_afx(fb0.dir)) {
case 0: open_afxbackup(fb0.dir);
freeze(fb0.dir);
fclose(file3);
fclose(file2);
if (flg_unpacked==0) {
unlink(fb0.dir);
if (rename(backup2,fb0.dir) != 0)
error(RENAMEERR, fb0.dir);
} else
unlink(backup2);
break;
case 1: printf("%s\n already in AFX-format\n",fb0.dir); break;
case 2: printf("%s\n already in LHarc-format\n",fb0.dir); break;
case 3: printf("%s\n Program-file\n",fb0.dir); break;
}
if (file2 != NULL) fclose(file2);
if (file3 != NULL) fclose(file3);
cnt++;
if ((f0 = fb0.next) != NULL) { /* make header of the next */
p = mkhdr(f0, &Hdr2); /* file in file list */
}
}
return cnt;
}
/*}}} */
/*{{{ pack_afx: pack-afx*/
void pack_afx(void)
{
int cnt;
char *p;
mklist(); /* make a file list */
if (Nfile == 0) {
error(NOFILEERR, NULL);
}
FlgMethod=0;
pack_aafx();
#ifndef __TOS__
freemem(seg);
#else
free (fbuf);
#endif
}
/*}}} */
/*{{{ freshen: f command*/
/*******************************
f command
*******************************/
void freshen(void)
{
uchar path[MAXPATH];
int c;
int cnt = 0;
openrwarc1(); /* open an archive */
message("Freshening archive", arcname);
openbackup1(); /* rename the archive to temp. */
openbackup2(); /* open temp. for a new archive */
while (gethdr(file1, &Hdr1)) {
c = 0;
if (matchpat(filename)) {
stpcpy(stpcpy(path, basedir), filename);
if ((file3 = fopen(path, "rb")) != NULL) {
sethdr(filename, getfattr(path), &Hdr2);
if (flg_c || FTimeToULong (Hdr1.Ftime) <
FTimeToULong (Hdr2.Ftime)) {
c = 1; /* found the file to be updated */
}
}
}
if (c) {
freeze(path); /* do updating */
cnt++;
fseek(file1, Hdr1.PacSiz, SEEK_CUR);
} else {
copyold();
}
if (file3)
fclose(file3);
}
endofupdate(cnt); /* end-of-job process */
}
/*}}} */
/*{{{ tstdir: test the file which should be melted*/
/*******************************
test the file which
should be melted
*******************************/
int tstdir(uchar *name)
{
uchar path[MAXPATH], *p, yn;
struct ffblk ffb;
Again:
p = name;
if (*p && p[1] == ':') /* skip a drive name */
p += 2;
if (*p == '\\') /* skip a root mark('\') */
p++;
yn = flg_m ? 'Y' : 'N';
while ((p = strchr(p, '\\')) != NULL) { /* skip to next '\' */
memcpy(path, name, p - name);
path[p - name] = '\0';
if (findfirst(path, &ffb, 0x1f)) { /* Is there this directory? */
if (yn == 'N') {
printf("'%s' : %s", name, M_MKDIR);
yn = getyn();
}
if (yn == 'N') {
return FAULT;
} else {
if (strcmp(path,".") != 0)
if (mkdir(path)) { /* make directory */
error(MKDIRERR, path);
}
}
} else {
if ((ffb.ff_attrib & 0x10) == 0) {
error(MKDIRERR, path); /* if the name isn't directory */
}
}
p++;
}
if (! findfirst(name, &ffb, 0x1f)) { /* if a file has the same name */
if (ffb.ff_attrib & 0x01 && ffb.ff_attrib != Hdr1.Attr) {
/* if the file is read-only, */
/* attributes must match */
fprintf(stderr, "'%s' %s\n", M_RDONLY);
return FAULT;
}
yn = 'Y';
#ifdef __TOS__
if (flg_c == 0 && UnixFile == 0) {
#else
if (flg_c == 0) {
#endif
if (((ulong)ffb.ff_fdate << 16) + (ulong)ffb.ff_ftime
< FTimeToULong (Hdr1.Ftime)) { /* compare time stamps */
yn = 'Y';
} else {
printf("Skipped : '%s' : New or same file exists.\n", name);
yn = 'N';
}
}
if (yn == 'Y' && flg_m == 0) {
fprintf(stderr, "'%s' : %s", name, M_OVERWT);
yn = getynr(); /* may overwrite? */
if (yn == 'R') {
printf(M_ENTERNEW);
scanf("%s",name);
goto Again;
}
}
if (yn == 'N') {
return FAULT;
}
setfattr(name, 0x20); /* reset attributes */
}
return SUCCS;
}
/*}}} */
/*{{{ tstID: read header-ID (method)*/
/*******************************
read header-ID (method)
*******************************/
int tstID(uchar *h)
{
int m;
static uchar IDpat[6][6] =
{"-lz4-", "-lz5-", "-lh0-", "-lh1-","-lh5-","-afx-"};
/* 0 1 2 3 4 5 */
m = (int)((sizeof IDpat) / (sizeof IDpat [0]));
while (m >= 0 && memcmp(h, IDpat[m], 5)) {
m--;
}
if (m==5) m=1;
return m;
}
/*}}} */
/*{{{ Dos1File: Dateiname nach 8+3 Zeichen wandeln*/
#ifdef __TOS__
char LegalChar(char c)
{
if (c <= 32) return 0;
if (c == '*' || c == '?') return 0;
return 1;
}
char *Dos1File(char *s, char *d) /* Ein Dateiname ohne Ordner wird überprüft */
{
char c,*t;
int p;
int l;
int i;
int j;
int k;
int m;
/* Suche von hinten den letzten Punkt. i ist die Position des
letzten Zeichens vor der Extension */
l = strlen(s);
for (i=l; i>=0;i--) if (s[i] == '.') break;
m = i-1;
if (i<=0) m = l;
/* Kopiere maximal 8 Zeichen des Dateinamens. Überspringe Punkte
und illegale Zeichen */
j = 0; k = 0;
t=s;
for (j = 0; j<=7; j++) {
c = *t++;
if (i>0) if (k++>i) break;
if (c=='\0') break;
if (j > m) break;
if (c != '.' && c > 32 && c != ':') {
if (LegalChar(c)) *d++ = c;}
else j--;
}
if (i>0) {
*d++ = '.';
i++;
for (j=0; j<=2; j++) {
c=s[i++];
if (c==0) break;
if (c > 32 && c != ':') if (LegalChar(c)) *d++ = c;
}
}
*d='\0';
return d;
}
/*}}} */
/*{{{ DosFile: File mit Ordnername nach 8+3 wandeln*/
/* Auftrennen des Files in einzelne Ordner (falls nötig) und anpassung
jedes Ordners an 8+3 Zeichen */
void DosFile(char *s)
{
char file[128], *f=file;
char dest[128], *d=dest;
char c,*s1=s;
*d=0;
while (( c= *s++) != 0) {
if (c=='/') c = '\\';
if (c==':' || c == '\\') {
*d=0;
f=Dos1File(dest,f);
*f++=c; *f='\0';
d=dest;
} else *d++=c;
}
*d=0;
f=Dos1File(dest,f);
strcpy(s1,file);
}
#endif
/*}}} */
/*{{{ extract: a,x,p,t command*/
/*******************************
e, x, p, t command
*******************************/
int extract(void)
{
uchar *p, *q;
int m;
int cnt = 0;
openarc1(); /* open an archive */
setvbuf(file1, buf2, _IOFBF, 1024);
message("Extract from", arcname);
if (flg_v == 1)
fprintf(file3, "Extract from '%s'\n", arcname);
UseExthdr=1;
while ((p = gethdr(file1, &Hdr1)) != NULL) {
if (matchpat(filename)) {
arcpos0 = ftell(file1) + Hdr1.PacSiz;
infile=file1;
MKinputbuf(Hdr1.PacSiz);
if (cmd == 'E') { /* if extract command, */
if (flg_x) { /* get the destination path name */
p = stpcpy(pathname, basedir);
if (filename[0] == '\\') {
p = pathname;
if (*p && p[1] == ':') {
p += 2;
}
}
stpcpy(p, filename);
} else {
stpcpy(stpcpy(pathname, basedir), p);
}
}
slash2yen(pathname);
strcpy(dospathname,pathname);
if (pathname[0] == 0)
#ifdef __TOS__
DosFile(dospathname);
UnixFile = strcmp(dospathname,pathname);
if (dospathname[strlen(dospathname)-1]=='\\')
goto weiter;
#endif
m=tstID(Hdr1.HeadID);
if (cmd != 'E' || tstdir(dospathname)) {
if ((m = tstID(Hdr1.HeadID)) < 0) {
printf("Skipped : '%s' : Unknown method\n", pathname);
} else
{
cnt++;
p = "Melting ";
q = "Melted ";
switch (cmd) {
case 'X':
case 'E':
if (flg_d == 0) printf("%s ", pathname);
file3 = fopen(outfname = dospathname, "wb");
break;
case 'T':
if (flg_d == 0) printf("%s ", filename);
#ifndef __TOS__
file3 = fopen ("nul", "wb");
#else
file3 = NULL; /* no NUL-Device supported! */
#endif
p = "Testing ";
q = "Tested ";
break;
case 'P':
if (flg_v != 2)
fprintf(file3, "<<< %s >>>\n", filename);
if (flg_v)
printf("%s ", filename);
fflush(file3);
setmode(fileno(file3), O_BINARY);
break;
}
#ifndef __TOS__
if ((ioctl(fileno(file3), 0) & 0x82) == 0x82) {
flg_n = 1; /* Console output ? */
} else {
setvbuf(file3, buf3, _IOFBF, BUFFERSIZ);
}
#else
if (file3 != NULL) {
if (file3 == stdout) {
flg_n = 1; /* Console output ? */
} else {
outfile=file3;
/* MKoutputbuf(); */
/* setvbuf(file3, buf3, _IOFBF, BUFFERSIZ); */
}
} else OutBuf=NULL;
#endif
if (m != 4)
blkdisp(Hdr1.OrgSiz, p);
else
blkdisp(Hdr1.OrgSiz/2,p);
outfile = file3;
infile = file1;
textsize = Hdr1.OrgSiz;
codesize = Hdr1.PacSiz;
crc = 0;
if (m == 3) {
Decode(); /* extract LHarc's file */
} else if (m == 1) {
DecodeOld(); /* extract LArc's file */
} else if (m == 4) {
decode_lh5(Hdr1.OrgSiz,Hdr1.PacSiz);
} else {
crcflg = 1;
copyfile(infile, outfile, Hdr1.OrgSiz);
crcflg = 0; /* only stored file */
}
fflush(file1);
fseek(file1,ftell(file1),0);
setvbuf(file1, buf2, _IOFBF, 1024);
Mfree(TheInputBuf);
if (file3 != NULL) {
Mfree(TheOutputBuf);
}
if (file3 != NULL && fflush(file3)) {
error(WTERR, outfname);
}
if (pathname[0] != 0)
if (cmd == 'E') {
setftime(fileno(file3), &Hdr1.Ftime);
fclose(file3);
setfattr(pathname, Hdr1.Attr);
file3 = NULL;
} else if (cmd == 'T') {
#ifndef __TOS__
fclose(file3);
#endif
} else {
setmode(fileno(file3), O_TEXT);
if (flg_v != 2)
fprintf(file3, "\n");
}
curback();
if (getcrc (&Hdr1) != crc) {
errorlevel = 1; /* test CRC */
printf("CRC err\n");
if (flg_m == 0) getchar();
} else if (cmd != 'P' || flg_v != 0) {
if (flg_d == 0) printf("%s\n", q);
}
}
}
weiter:
fseek(file1, arcpos0, SEEK_SET); /* move pointer to next file */
} else {
fseek(file1, Hdr1.PacSiz, SEEK_CUR);
}
}
fclose(file1);
file1 = NULL;
return cnt;
}
/*}}} */
/*{{{ delete: d command*/
/*******************************
d command
*******************************/
void delete(void)
{
int cnt = 0;
openrwarc1(); /* open archive */
if (patno == 0) {
error(NOFNERR, NULL);
}
message("Updating archive", arcname);
openbackup1(); /* rename to temporary name */
openbackup2(); /* open another temporary file */
while (gethdr(file1, &Hdr1)) {
if (matchpat(filename)) {
message("Deleting", filename);
cnt++;
fseek(file1, Hdr1.PacSiz, SEEK_CUR); /* skip file */
} else {
copyold();
}
}
endofupdate(cnt); /* end-of-job process */
}
/*}}} */
/*{{{ self: s command*/
/*******************************
s command
*******************************/
void self(void)
{
#ifndef __TOS__
uchar *p, /* *q,*/ buf[12], yn;
int flg, i;
long l, m, n;
void sfx(void), sfx2(void);
openarc1(); /* open archive */
message("Making Sfx from archive", arcname);
stpcpy(stpcpy(backup2, workdir), "lharc.)2(");
file2 = e_fopen(outfname = backup2, "w+b", MKTMPERR);
/* open temporary */
while (gethdr(file1, &Hdr1)) {
flg = 0;
if (matchpat(filename)) {
if (flg_d == 0) printf("Extracting '%s' ", filename);
if (tstID(Hdr1.HeadID) < 2) {
printf("(not supported) skipped.");
} else {
if (flg_x == 0 && (p = strrchr(filename, '\\')) != NULL) {
p++; /* delete directory part */
Hdr1.Fname[0] = strlen(p);
i = p - filename;
Hdr1.HeadSiz -= i;
memcpy(Hdr1.Fname + 1, Hdr1.Fname + 1 + i,
Hdr1.Fname[0] + 2);
Hdr1.HeadChk = mksum(&Hdr1); /* recalculate sum */
}
wthdr(&Hdr1);
copyfile(file1, file2, Hdr1.PacSiz);
flg = 1;
}
printf("\n");
}
if (flg == 0) {
fseek(file1, Hdr1.PacSiz, SEEK_CUR);
}
}
fclose(file1);
if (putc(0, file2) == EOF) /* end-mark of archive */
error(WTERR, backup2);
if ((l = ftell(file2)) <= 1) {
goto self9;
}
if (flg_x == 0) {
m = (uchar*)sfx2 - (uchar*)sfx; /* size of sfx routine */
} else {
m = (uchar*)usage - (uchar*)sfx2;
}
n = l + m; /* total size of sfx file */
rewind(file2);
infname = backup2;
extfn(arcname, buf); /* make the name of sfx */
p = stpcpy(pathname, basedir);
strcpy(&buf[8], "COM");
if (flg_x || n > 0xfe80ul) {
strcpy(&buf[8], "EXE");
}
packfn(p, buf);
if ((getfattr(pathname) & 0x8000) == 0) { /* if the same name exists */
fprintf(stderr, "'%s' : %s", pathname, M_OVERWT);
yn = getyn(); /* may overwrite */
if (yn == 'N') {
goto self9;
}
}
file3 = e_fopen(outfname = pathname, "wb", MKFILEERR);
if (buf[8] == 'E') { /* if .EXE */
if (flg_x) {
n = m;
}
n += 0x20;
ExeHdr.page = (n + 511) / 512;
ExeHdr.byte = n % 512;
ExeHdr.minalloc = (flg_x ? 0x66c0 : 0x2560) / 0x10;
if (fwrite(&ExeHdr, 0x20, 1, file3) == 0)
error(WTERR, pathname);
}
movedata(_CS, (flg_x ? (unsigned)sfx2 : (unsigned)sfx),
_DS, (unsigned)buf2, m);
if (flg_x) {
memcpy(buf2 + 0x34, p, strlen(p)); /* large ver. */
} else {
*((uint *)buf2 + 1) = (l + m + 0x10f) / 0x10; /* small ver. */
}
if (fwrite(buf2, m, 1, file3) == 0) /* write sfx routine */
error(WTERR, pathname);
if (flg_x) {
if (fwrite(keyword, strlen(keyword) + 1, 1, file3) == 0)
error(WTERR, pathname);
}
copyfile(file2, file3, l); /* write an archive */
printf("\nCreated : '%s'\n", pathname);
fclose(file3);
self9:
fclose(file2);
unlink(backup2);
#else
fprintf (stderr, "Self-Extracting-Files: NOT YET IMPLEMENTED!!!\7\n");
errorlevel = 1;
longjmp (exit_jmp, 1); /* NOT YET IMPLEMENTED !!! */
#endif
}
/*}}} */
/*{{{ sysid*/
char *sysid( void )
{
char *s;
if (flg_k == 0) {
switch(SystemId) {
case 'M' : s="MSDOS "; break;
case '2' : s="OS/2 "; break;
case '9' : s="OS9 "; break;
case 'K' : s="OS/68K"; break;
case '3' : s="OS/386"; break;
case 'H' : s="HUMAN "; break;
case 'U' : s="UNIX "; break;
case 'C' : s="CP/M "; break;
case 'm' : s="Mac "; break;
case 'R' : s="Runser"; break;
case 'A' : s="Atari "; break;
default : s=" "; break;
}
} else s=" ";
return s;
}
/*}}} */
/*{{{ list: l,v command*/
/*******************************
l, v command
*******************************/
void list(void)
{
uint rt;
uchar buf[79], *p,*b;
static uchar attr[7] = "ohs--a";
int i, j, k, Fno;
ulong Osize, Psize;
Osize = Psize = 0L;
Fno = 0;
openarc1(); /* open archive */
UseExthdr=1;
#ifdef German
printf("Inhalt von : '%s'\n\n", arcname);
printf(" Name Original Gepackt Rate"
" Datum Zeit Attr Typ CRC\n");
#else
printf("Listing of archive : '%s'\n\n", arcname);
printf(" Name Original Packed Ratio"
" Date Time Attr Type CRC\n");
#endif
printf("-------------- -------- -------- ------"
" -------- -------- ---- ----- ----\n");
while ((p = gethdr(file1, &Hdr1)) != NULL) {
if (matchpat(filename)) {
rt = ratio(Hdr1.PacSiz, Hdr1.OrgSiz);
sprintf(buf, " %10lu%10lu %3d.%1d%% "
"%2d-%02d-%02d %2d:%02d:%02d ---w %04X\n",
Hdr1.OrgSiz, Hdr1.PacSiz, rt / 10, rt % 10,
(Hdr1.Ftime.ft_year + 80) % 100, Hdr1.Ftime.ft_month,
Hdr1.Ftime.ft_day, Hdr1.Ftime.ft_hour,
Hdr1.Ftime.ft_min, Hdr1.Ftime.ft_tsec * 2,
getcrc (&Hdr1));
memcpy(&buf[65], Hdr1.HeadID, 5);
for (i = 0, j = 1; i < 6; i++, j <<= 1) { /* attributes */
if (Hdr1.Attr & j) {
k = attr[i];
if (i <= 2) {
buf[63 - i] = k;
} else {
buf[60] = k;
}
}
}
if (flg_x) {
printf("%s\n", filename); /* display in 2 lines */
p=sysid(); b = buf;
while (*p != 0) *b++=*p++;
if (comment[0] != 0) printf("%s\n",comment);
} else {
if (p != filename) { /* display in one line */
*buf = '+';
}
memcpy(&buf[2], p, strlen(p));
}
printf("%s", buf);
Fno ++;
Osize += Hdr1.OrgSiz;
Psize += Hdr1.PacSiz;
}
if (fseek(file1, Hdr1.PacSiz, 1))
break;
}
if (Fno) {
printf("-------------- -------- -------- ------"
" -------- --------\n");
rt = ratio(Psize, Osize);
getftime(fileno(file1), &arcstamp);
printf(" %3d files %10lu%10lu %3d.%1d%% "
"%2d-%02d-%02d %2d:%02d:%02d\n",
Fno, Osize, Psize, rt / 10, rt % 10,
(arcstamp.ft_year + 80) % 100, arcstamp.ft_month,
arcstamp.ft_day, arcstamp.ft_hour,
arcstamp.ft_min, arcstamp.ft_tsec * 2);
} else {
printf(" no file\n");
}
fclose(file1);
}
/*}}} */
/*{{{ getsw: get switches*/
/*******************************
get switches
*******************************/
void getsw(uchar *p)
{
#ifndef __TOS__
static uchar flg[] = "rpxmacntvwyb";
static uchar *flgpos[] = {&flg_r, &flg_p, &flg_x, &flg_m,
&flg_a, &flg_c, &flg_n, &flg_t,
&flg_v, &flg_w};
#else
static uchar flg[] = "rpxmacntvwhybludoske5";
static uchar *flgpos[] = {&flg_r, &flg_p, &flg_x, &flg_m,
&flg_a, &flg_c, &flg_n, &flg_t,
&flg_v, &flg_w, &flg_h};
#endif
int i;
uchar s;
uchar *q;
while ((s = *p++) != 0) {
q = strchr(flg, s); /* search switch */
if (q) {
i = (int)(q - flg);
if (*p == '+') {
*flgpos[i] = 1;
p++;
} else if (*p == '-') {
*flgpos[i] = 0;
p++;
} else if (*p == '2') {
*flgpos[i] = 2;
p++;
} else if (s == 'v' && *p) {
if (flg_v == 0) /* process of '/vSTRING' */
flg_v = 1;
pager = p;
p = "";
} else if (s == 'y') flg_arc = 1;
else if (s == 'k') { flg_k=1; elen=0; }
else if (s == 'b') {
flg_arc=1;
flg_backup=1;
} else if (s == '5') flg_5=1;
else if (s == 'l') FlgMethod=0;
else if (s == 'o') FlgMethod=1;
else if (s == 's') flg_s=1;
else if (s == 'u') flg_u = 1;
else if (s == 'e') flg_e = 1;
else if (s == 'w' && *p) {
flg_w = 1; /* process of '/wSTRING' */
wdir = p;
p = "";
} else if (s == 'd') flg_n = flg_d = 1;
else {
if (*flgpos[i]) { /* flip-flop */
*flgpos[i] = 0;
} else {
*flgpos[i] = 1;
}
}
if (s == 'r' && flg_r > 0) {
flg_x = 1;
}
#ifndef __TOS__
} else if (s == 'k') {
keyword = p;
p = "";
#endif
}
else {
if (s == '?') usage();
error(INVSWERR, NULL);
}
}
}
/*}}} */
/*{{{ executecmd: execute command*/
/*******************************
execute command
*******************************/
void executecmd(void)
{
int cnt;
switch (cmd) {
case 'A':
flg_c++;
case 'U':
case 'M':
append();
break;
case 'C':
pack_afx();
break;
case 'F':
freshen();
break;
case 'P':
if (flg_v == 0) {
file3 = stdout;
goto common;
}
stpcpy(stpcpy(pathname, workdir), "LHARC.TMP"); /* view files */
file3 = e_fopen(outfname = pathname, "w", MKTMPERR);
cnt = extract();
fclose(file3);
if (cnt) /* if any files extracted */
#ifndef __TOS__
stpcpy(stpcpy(stpcpy(buf2, pager), " "), pathname);
execute(buf2); /* execute by INT 0x2e */
#else
{
int retcode;
exec (pager, pathname, "", &retcode);
}
#endif
#if 0
spawnlp(P_WAIT, pager, pager, pathname, NULL);
#endif
unlink(pathname);
break;
case 'T':
tstflg = 1;
goto common;
case 'X':
case 'E':
cmd = 'E';
common:
flg_v = 0;
extract();
break;
case 'V':
flg_x++;
case 'L':
list();
break;
case 'D':
delete();
break;
case 'S':
self();
break;
}
if (!flg_d) putchar('\n');
}
/*}}} */
/*{{{ recoverbrk: handle userbreak*/
/*******************************
handle userbreak
*******************************/
#ifndef __TOS__
int cbrk;
void recovercbrk(void) {
setcbrk(cbrk);
}
#endif
/*}}} */
/*{{{ OneNewFile:*/
void OneNewFile(char *p)
{
char *s;
s = strchr(p,'\n');
if (s != NULL) *s='\0';
if (patno == 0 && basedir == NULL &&
(strrchr(p, '\\') == p + strlen(p) - 1 ||
p[strlen(p) - 1] == ':')) {
basedir = p; /* get base (or home) directory */
} else if (patno >= MAX_PAT) {
message("File table overflow. ignore", p);
} else {
patpath[patno] = p;
extfn(p, patfile[patno]);
patno++; /* regist path names */
}
}
/*}}} */
/*{{{ newfile*/
void newfile(char *p)
{
char file[128]; /* Dateiname bei &datei */
FILE *f;
if (*p == '&')
{
if (strcmp("-",&p[1]) == 0)
f=stdin; else f=fopen(&p[1],"r");
if (f != NULL)
{
while ( fgets(file,127,f) != NULL)
OneNewFile(strdup(file)); /* regist copy of filecontents */
fclose(f);
}
} else OneNewFile(p);
}
/*}}} */
/*{{{ argv_main: main routine*/
/*******************************
main routine
*******************************/
#ifndef __GEM__
#ifdef __TOS__
int argvmain(int argc, uchar **argv,uchar **envp)
#else
int main(int argc, uchar *argv[])
#endif
{
uchar *p, *q, *env, *env9;
uchar ptitel=0;
int yn;
extern char title[];
struct ffblk ffb;
FILE *fp;
char buffer[256];
if (!setjmp (exit_jmp)) {
#ifndef __TOS__
ctrlbrk(userbreak); /* set vector for '^C' */
cbrk = getcbrk();
setcbrk(1);
atexit(recovercbrk);
#endif
remove("LHARC.)1(");
remove("LHARC.)2(");
mkcrc(); /* make CRC table */
swchar = getswchar(); /* get the setting of switch char */
argc--;
argv++;
if (argc-- == 0)
{
flg_h = 1;
usage(); /* if no parameter given */
}
p = (argv++)[0];
cmd = toupper(*p);
if (strlen(p) - 1 || strchr("EXTDLVAUMFPSC", cmd) == 0) {
cmd = 'X'; /* if no command, assume 'X' command */
argc++;
argv--;
flg_x = 1; /* @@25.5.91 Ohne Kommando x -rm */
flg_m = 1;
}
cmdupdate = (int)strchr("AUMFD", cmd);
/* command updating archive? */
if ((env = getenv("TMP")) != NULL) { /* get 'TMP' from environment */
wdir = env;
flg_w = 1;
}
if ((env = getenv("LHARC")) != NULL) {
/* get 'LHARC' from environment */
for (p = env; *p != '\0'; p++) {
if (*p == ' ' || *p == '\x08')
*p = '\0';
}
env9 = p;
p = env;
while (p < env9) {
while (*p == '\0') p++;
if (*p == swchar || *p == '-') p++;
getsw(p);
while (*p) p++;
}
}
patno = -1;
if (cmd == 'C') patno=0;
basedir = NULL;
while (argc--) {
p = (argv++)[0];
if (*p == swchar || *p == '-') {
getsw(++p);
} else {
if (ptitel == 0 && flg_d == 0) {
puts(title); /* output title */
if ((fp = fopen("lharc.ttp","rb")) != NULL ||
(fp = fopen("lzh.ttp","rb")) != NULL ||
(fp = fopen("lharcd.ttp","rb")) != NULL) {
fread(buffer,1,256,fp);
if (strncmp(buffer+30,"LArc's PFX",10) == 0)
printf(morefiles);
fclose(fp);
}
putchar('\n');
ptitel=1;
}
strupr(p);
slash2yen(p); /* convert '/' to '\' */
/* in japanese version */
if (patno < 0) { /* get archive name */
strcpy(arcname, p);
if ((p = strrchr(arcname, '\\')) == NULL) {
p = arcname; /* pointer of the part of file name */
}
if ((q = strchr(p, '.')) == NULL) {
strcat(arcname, ".LZH"); /* if no extension */
} else if (strcmp(".LZH", q) && flg_m == 0 && cmdupdate) {
fprintf(stderr, M_NOTLZH, arcname);
yn = getyn(); /* if the extension is not '.LZH' */
if (yn == 'N') {
errorlevel = 1;
longjmp (exit_jmp, 1);
}
}
patno++;
} else {
newfile(p); /* Register file or files */
}
}
}
if (patno < 0) {
error(NOARCNMERR, NULL);
}
if (patno == 0 && cmd != 'D') { /* if no name given */
extfn(patpath[0] = patnul, patfile[0]); /* '*.*' is assumed */
patno++;
}
p = stpcpy(workdir, wdir) - 1;
if (*workdir != '\0' && strrchr(workdir, '\\') != p && *p != ':') {
strcat(workdir, "\\"); /* concatenate '\' after the work dir. */
}
if (cmdupdate) {
if (strchr(arcname, '*') || strchr(arcname, '?')) {
error(NOARCERR, arcname);
} /* when updating archive, wild cards can't used */
executecmd();
}
else {
if (cmd == 'C') executecmd();
else {
if (findfirst(arcname, &ffb, 0x07)) {
error(NOARCERR, arcname);
}
do {
strcpy(backpath(arcname), ffb.ff_name);
executecmd();
} while (!findnext(&ffb));
if (cmd != 'L' && cmd != 'V')
tstpat(); /* whether all given names were used? */
}
}
}
#ifdef __TOS__
if (flg_h)
{
fflush (stdin); /* wait for keystroke when used */
printf (M_PRESSKEY); /* with GEM-Desktop */
getch ();
putchar ('\n');
}
#endif
return errorlevel;
}
/*}}} */
/*{{{ main: argv calculations*/
int main (int argc, char *argv[], char *envp[])
{
char **myargv;
extern BASPAG *_BasPag;
char *env;
char *startpar;
char *oldline;
int count = 0;
int i;
Fsetdta (&_mydta);
/* Anfang der alten Kommandozeile */
oldline = &_BasPag->p_cmdlin[1];
/* Flag fuer Verwendung von ARGV */
if (_BasPag->p_cmdlin[0] != 127)
return argvmain (argc, argv, envp);
/* Zeiger auf Env-Var merken */
env = getenv("ARGV");
if (!env)
return argvmain (argc, argv, envp);
/* alle weiteren envp's loeschen */
i = 0;
while (strncmp (envp[i], "ARGV", 4)) i++;
envp[i] = NULL;
/* alles, was dahinter kommt, abschneiden */
if (env[0] && env[-1])
{
*env++ = 0; /* kill it */
while (*env++);
}
/* Parameterstart */
startpar = env;
while (*env)
{
count++;
while (*env++);
}
/* Speicher fuer neuen Argument-Vektor */
myargv = Malloc ((count+1)*sizeof (char *));
env = startpar;
count = 0;
while (*env)
{
myargv[count++] = env;
while (*env++);
}
myargv[count] = NULL;
/* moeglichst viele Parameter in alte Kommandozeile */
{
int i;
*oldline = 0;
i = 1;
while ((i < count) && (strlen (oldline) + strlen (myargv[i]) < 120))
{
if (i > 1) strcat (oldline, " ");
strcat (oldline, myargv[i]);
i++;
}
if (i < count) strcat (oldline, " ...");
}
/* und ...argvmain() starten */
count = argvmain (count, myargv, envp);
Mfree (myargv);
return count;
}
#endif
/*}}} */